#ifndef __FILE_SRV__
#define __FILE_SRV__

#include "fs_proto.h"
#include "volume_proto.h"
#include "cache.h"
#include "chunk.h"
#include "fileinfo.h"
#include "lichstor.h"

typedef struct __volume_ctl_param_t {
        int record;

        // volume level
        volid_t volid;

        // chunk level
        chkid_t chkid;
        chkinfo_t *chkinfo;

        buffer_t *buffer;
} volume_ctl_param_t;

typedef struct __volume_ctrl_op_t {
        int (*get)(mcache_entry_t **cent, const chkid_t *chkid);
} volume_ctl_op_t;


int volume_ctl_init(uint64_t max_chunk);

int volume_ctl_destroy_all();
int volume_ctl_dump_memory(uint64_t *memory);
int volume_ctl_vfm_add(const volid_t *volid, const nid_t *nid, int count);

/**
 * 引用计数
 *
 * @param fileid
 * @param cent
 * @return
 */
int volume_ctl_get(const fileid_t *fileid, mcache_entry_t **cent);
void volume_ctl_release(mcache_entry_t *cent);

// volume
int volume_ctl_move(const fileid_t *fileid, const nid_t *nid, int count);
int volume_ctl_localize(const fileid_t *fileid, int idx);

int volume_ctl_getpool(const fileid_t *chkid, char *pool);

int volume_ctl_getattr(const fileid_t *chkid, fileinfo_t *fileinfo);
int volume_ctl_setattr(const fileid_t *chkid, fileinfo_t *fileinfo, const setattr_t *setattr);

int volume_ctl_lookup_srv(const fileid_t *chkid, const fileid_t *parent);

int volume_ctl_stat(const volid_t *volid, filestat_t *filestat, off_t off, size_t size);
int volume_ctl_check_ready(const fileid_t *fileid);
int volume_ctl_check_exists(const volid_t *volid, int *exists);

int volume_ctl_move(const fileid_t *fileid, const nid_t *nid, int count);
int volume_ctl_localize(const fileid_t *fileid, int idx);

int volume_ctl_read(const io_t *io, buffer_t *buf, int record);
int volume_ctl_write(const io_t *io, const buffer_t *buf, int record);

int volume_ctl_unmap(const io_t *io, int record);

int volume_ctl_table_read(const fileid_t *fileid, const chkid_t *chkid,
        buffer_t *buf, size_t size, off_t offset);
int volume_ctl_table_write(const fileid_t *fileid, const chkid_t *chkid,
        const buffer_t *buf, size_t size, off_t offset);

int volume_ctl_write_direct(mcache_entry_t *cent, const io_t *io, const buffer_t *buf, int record);
int volume_ctl_read_direct(mcache_entry_t *cent, const io_t *io, buffer_t *buf, int record);

// chunk
int volume_ctl_chunk_allocate(const fileid_t *fileid, const chkid_t *chkid, int chknum, int fill);

int volume_ctl_chunk_cleanup(const fileid_t *fileid, const chkid_t *chkid,
                             const nid_t *_nid, uint64_t meta_version);

int volume_ctl_newchunk(const fileid_t *fileid, const chkid_t *chkid, const buffer_t *buf);
int volume_ctl_discard(const fileid_t *fileid, const chkid_t *chkid);

int volume_ctl_chunk_exist(const volid_t *volid, const chkid_t *chkid, int *exist);
int volume_ctl_chunk_getinfo(const fileid_t *parent, const fileid_t *chkid, chkinfo_t *chkinfo);

int volume_ctl_chunk_num(const volid_t *volid, func2_t func2, void *arg);
int volume_ctl_chunk_unintact(const volid_t *volid, func3_t func3, void *arg, int deep);
int volume_ctl_chunk_iterator(const fileid_t *fileid, func2_t func2, void *_arg);
int volume_ctl_chunk_iterator_with_cursor(const volid_t *volid, func2_t func2, void *arg);
int volume_ctl_chunk_iterator2_with_cursor(const volid_t *volid, uint64_t volsize, uint64_t step,
                                           uint64_t find, uint64_t *cursor, func2_t func2, void *arg);

int volume_ctl_chunk_check(const fileid_t *fileid, const chkid_t *chkid);

int volume_ctl_chunk_sync(const fileid_t *fileid, const chkid_t *chkid, int force, int *oflags);
int volume_ctl_chunk_sync_force(const nid_t *srcnid, const volid_t *volid, const chkid_t *chkid, int chknum, int *retval);

int volume_ctl_chunk_move(const fileid_t *fileid, const chkid_t *chkid, const nid_t *dist, int dist_count);

int volume_ctl_chunk_migrate(const fileid_t *parent, const chkid_t *chkid, uint32_t force,
                         chkinfo_t *chkinfo);
int volume_ctl_chunk_reject(const fileid_t *parent, const chkid_t *chkid, const nid_t *nid,
                          chkinfo_t *chkinfo);

int volume_ctl_chunk_set(const fileid_t *parent, const chkid_t *chkid,
                         const nid_t *nid, int status);
int volume_ctl_chunk_update(const fileid_t *parent, const chkinfo_t *chkinfo, const nid_t *owner, uint64_t info_version);

// VFM
int volume_ctl_vfm_get(const fileid_t *parent, const chkid_t *chkid, vfm_t *vfm);
int volume_ctl_vfm_set(const fileid_t *parent, const chkid_t *chkid, const vfm_t *vfm);
int volume_ctl_vfm_cleanup(const volid_t *volid, const chkid_t *tid);
int volume_ctl_vfm_stat(const volid_t *volid, int *count);

// xattr
int volume_ctl_xattr_set(const chkid_t *chkid, const char *key, const char *value,
                     uint32_t valuelen, int flag);
int volume_ctl_xattr_get(const chkid_t *chkid, const char *key, char *value, int *valuelen);
int volume_ctl_xattr_list(const chkid_t *chkid, char *buf, int *buflen);
int volume_ctl_xattr_remove(const chkid_t *chkid, const char *key);


// snapshot {{
int volume_ctl_snapshot_create(const fileid_t *fileid, const char *name, int p, const char *_site);

int volume_ctl_snapshot_create_nolock(const volid_t *, const char *, const char *, const uuid_t);
int volume_ctl_snapshot_remove_nolock(const volid_t *, const char *, const uuid_t);

int volume_ctl_snapshot_protect(const volid_t *volid, const snap_protect_param_t on);

int volume_ctl_snapshot_listopen(const fileid_t *parent, const char *uuid);
int volume_ctl_snapshot_list(const chkid_t *parent, const char *uuid, uint64_t offset, void *de, int *delen);
int volume_ctl_snapshot_listclose(const fileid_t *parent, const char *uuid);

int volume_ctl_snapshot_last(const fileid_t *fileid,
                             nid_t *snapnid, fileid_t *snapid, char *snapname, uint64_t *snap_version);
int volume_ctl_snapshot_prev(const volid_t *volid, const fileid_t *snapid,
                             fileid_t *previd, char *name, uint64_t *snap_version);
int volume_ctl_snapshot_lookup(const chkid_t *parent, const char *name,
                               chkinfo_t *chkinfo);

int volume_ctl_snapshot_updateparent(const fileid_t *fileid, const char *name, const uint64_t from);
int volume_ctl_snapshot_setfrom(const fileid_t *fileid, const uint64_t from);

int volume_ctl_snapshot_check(const volid_t *, const char *);
int volume_ctl_snapshot_isempty(const volid_t *volid, int *empty);

int volume_ctl_snapshot_read(const fileid_t *volid, const io_t *io, buffer_t *buf);
int volume_ctl_snapshot_read_meta(const fileid_t *volid, const io_t *io, const char *snap, buffer_t *buf);
int volume_ctl_lower_read(const fileid_t *volid, const io_t *io, buffer_t *buf);

int volume_ctl_snapshot_diff(const fileid_t *parent, const fileid_t *fileid, const fileid_t *snapdst,
                             buffer_t *buf, size_t size, off_t offset);

int volume_ctl_snapshot_wrlock(const volid_t *, uuid_t *);
int volume_ctl_snapshot_unlock(const volid_t *, const uuid_t);

// iscsi connections
int volume_ctl_connect(const fileid_t *fileid, const nid_t *nid, const char *addr);
int volume_ctl_disconnect(const fileid_t *fileid, const nid_t *peer, const char *addr);
int volume_ctl_connection(const fileid_t *fileid, const nid_t *peer, void *list, int *count);

// bh: bottom half tasks {{

int volume_ctl_cleanup(const fileid_t *fileid);

int volume_ctl_snapshot_remove(const fileid_t *fileid, const char *name, int force);
int volume_ctl_snapshot_cleanup_bh(const fileid_t *fileid, const char *name);

// int volume_ctl_snapshot_cleanup(const fileid_t *fileid);
int volume_ctl_snapshot_cleanup_direct(const fileid_t *fileid, const char *name);

int volume_ctl_snapshot_rollback(const fileid_t *fileid, const char *name);
int volume_ctl_snapshot_rollback_bh(const fileid_t *fileid);

int volume_ctl_snapshot_flat(const fileid_t *fileid, int idx, int force);
int volume_ctl_snapshot_flat_bh(const fileid_t *fileid);

// }}

#endif
